package org.zyj.io.example.case2;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * 写个专门处理Http请求的服务
 *
 * @author zhouyijin
 * @date 2022-01-17 15:52:51
 */
public class HttpServer {

    public static void main(String[] args) throws InterruptedException {
        final NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
        final NioEventLoopGroup workGroup = new NioEventLoopGroup(4);
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap //
                    .group(bossGroup, workGroup)//
                    .channel(NioServerSocketChannel.class)//
                    .option(ChannelOption.SO_BACKLOG, 128)//
                    .option(ChannelOption.SO_KEEPALIVE, true)//
                    .handler(new LoggingHandler(LogLevel.INFO))//
//                    .handler(null)//bossGroup的handler
                    .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            //每次建立连接都会执行一次这个方法, 来组建Channel的pipeline
                            //所以如果要做高性能的netty服务器, 可能需要考虑 handler的复用
                            System.out.println("initChannel...");
                            ch.pipeline()
                                    // workerGroup的handler, 自定义处理http协议的handler
                                    .addLast(new HttpServerCodec())//netty提供的处理http的编解码器
                                    .addLast(new HttpServerHandler())//自定义的业务处理handler
                            ;
                        }
                    });
            ChannelFuture channelFuture = serverBootstrap.bind(9987).sync();
            channelFuture.addListener((ChannelFutureListener) future -> {
                if (future.isSuccess()) {
                    System.out.println("服务器启动: 端口监听成功");
                } else {
                    System.out.println("服务器启动: 端口监听失败");
                }
            });
            channelFuture.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
        }
    }
}
